/******************** (C) COPYRIGHT 2018 merafour ********************
* Author             : 冷月追风@merafour.blog.163.com
* Version            : V1.0.0
* Date               : 8/1/2019
* Description        : IPMB协议与数据处理.
********************************************************************************
* merafour.blog.163.com
* merafour@163.com
* github.com/Merafour
*******************************************************************************/
#include "ipmc_protocol.h"
#include <string.h>
#include <QDebug>

#define SLAVE_OWN_ADDRESS                          0xC0

const struct ipmc_device_type ipmc_protocolObj::ipmc_device_table[8] =
{
    {0x01,   "电源板"},
    {0x02,   "主控板"},
    {0x03,   "交换板"},
    {0x04,   "计算板"},
    {0x05,   "X86 计算板"},
    {0x06,   "GPU 板 "},
    {0x07,   "时钟板"},
    {0x00,   "NULL"}
};
const struct ipmc_id_item ipmc_protocolObj::ipmc_id_table[20] =
{
    /* number, id , info*/
    {/* 1 */  0x01, "电源板上温度"},
    {/* 2 */  0x02, "28VDC"},
    {/* 3 */  0x03, "12VDC_MAIN"},
    {/* 4 */  0x04, "12VDC_AUX"},
    {/* 5 */  0x05, "5VDC_MAIN"},
    {/* 6 */  0x06, "5VDC_AUX"},
    {/* 7 */  0x07, "3V3DC_MAIN"},
    {/* 8 */  0x08, "3V3DC_AUX"},
    {/* 9 */  0x09, "12V main 输出电流"},
    {/*10 */  0x0A, "12V aux 输出电流"},
    {/*11 */  0x0B, "5V main 输出电流"},
    {/*12 */  0x0C, "5V aux 输出电流"},
    {/*13 */  0x0D, "3.3V main 输出电流"},
    {/*14 */  0x0E, "3.3V aux 输出电流"},
    {/*15 */  0x10, "MCU温度"},
    {/*16 */  0x11, "-12VDC_AUX"},
    {/*17 */  0x00, "NULL"},
    {/*18 */  0x00, "NULL"},
    {/*19 */  0x00, "NULL"},
    {/*20 */  0x00, "NULL"}
};

const struct vpx_ipmb_addr ipmc_protocolObj::vpx_ipmb_addr_table[32] =
{
//   ID | GAP | GA4 | GA3| GA2| GA1 | GA0 | recv | Hard | IPMB |
    {0  ,  0  ,  0  ,  0 ,  0 ,  0  ,  0  ,  0   , 0xEE , 0xEE }, // Geographical Address of “0” is  Invalid
    {1  ,  0  ,  0  ,  0 ,  0 ,  0  ,  1  ,  0   , 0x41 , 0x82 },
    {2  ,  0  ,  0  ,  0 ,  0 ,  1  ,  0  ,  0   , 0x42 , 0x84 },
    {3  ,  1  ,  0  ,  0 ,  0 ,  1  ,  1  ,  0   , 0x43 , 0x86 },
    {4  ,  0  ,  0  ,  0 ,  1 ,  0  ,  0  ,  0   , 0x44 , 0x88 },
    {5  ,  1  ,  0  ,  0 ,  1 ,  0  ,  1  ,  0   , 0x45 , 0x8A },
    {6  ,  1  ,  0  ,  0 ,  1 ,  1  ,  0  ,  0   , 0x46 , 0x8C },
    {7  ,  0  ,  0  ,  0 ,  1 ,  1  ,  1  ,  0   , 0x47 , 0x8E },
    {8  ,  0  ,  0  ,  1 ,  0 ,  0  ,  0  ,  0   , 0x48 , 0x90 },
    {9  ,  1  ,  0  ,  1 ,  0 ,  0  ,  1  ,  0   , 0x49 , 0x92 },
    {10 ,  1  ,  0  ,  1 ,  0 ,  1  ,  0  ,  0   , 0x4A , 0x94 },
    {11 ,  0  ,  0  ,  1 ,  0 ,  1  ,  1  ,  0   , 0x4B , 0x96 },
    {12 ,  1  ,  0  ,  1 ,  1 ,  0  ,  0  ,  0   , 0x4C , 0x98 },
    {13 ,  0  ,  0  ,  1 ,  1 ,  0  ,  1  ,  0   , 0x4D , 0x9A },
    {14 ,  0  ,  0  ,  1 ,  1 ,  1  ,  0  ,  0   , 0x4E , 0x9C },
    {15 ,  1  ,  0  ,  1 ,  1 ,  1  ,  1  ,  0   , 0x4F , 0x9E },
    {16 ,  0  ,  1  ,  0 ,  0 ,  0  ,  0  ,  0   , 0x50 , 0xA0 },
    {17 ,  1  ,  1  ,  0 ,  0 ,  0  ,  1  ,  0   , 0x51 , 0xA2 },
    {18 ,  1  ,  1  ,  0 ,  0 ,  1  ,  0  ,  0   , 0x52 , 0xA4 },
    {19 ,  0  ,  1  ,  0 ,  0 ,  1  ,  1  ,  0   , 0x53 , 0xA6 },
    {20 ,  1  ,  1  ,  0 ,  1 ,  0  ,  0  ,  0   , 0x54 , 0xA8 },
    {21 ,  0  ,  1  ,  0 ,  1 ,  0  ,  1  ,  0   , 0x55 , 0xAA },
    {22 ,  0  ,  1  ,  0 ,  1 ,  1  ,  0  ,  0   , 0x56 , 0xAC },
    {23 ,  1  ,  1  ,  0 ,  1 ,  1  ,  1  ,  0   , 0x57 , 0xAE },
    {24 ,  1  ,  1  ,  1 ,  0 ,  0  ,  0  ,  0   , 0x58 , 0xB0 },
    {25 ,  0  ,  1  ,  1 ,  0 ,  0  ,  1  ,  0   , 0x59 , 0xB2 },
    {26 ,  0  ,  1  ,  1 ,  0 ,  1  ,  0  ,  0   , 0x5A , 0xB4 },
    {27 ,  1  ,  1  ,  1 ,  0 ,  1  ,  1  ,  0   , 0x5B , 0xB6 },
    {28 ,  0  ,  1  ,  1 ,  1 ,  0  ,  0  ,  0   , 0x5C , 0xB8 },
    {29 ,  1  ,  1  ,  1 ,  1 ,  0  ,  1  ,  0   , 0x5D , 0xBA },
    {30 ,  1  ,  1  ,  1 ,  1 ,  1  ,  0  ,  0   , 0x5E , 0xBC },
    {31 ,  0  ,  1  ,  1 ,  1 ,  1  ,  1  ,  0   , 0x5F , 0xBE },
};

//ipmc_protocolObj::ipmc_protocolObj(struct ipmb_cpu_data &_data) : _cpu_data(_data)// , _ipmc_data(_data._ipmc)
ipmc_protocolObj::ipmc_protocolObj()
{
    uint8_t _size=0;
    uint8_t index=0;
    uint8_t j=0;
    cmd_rqSeq = 0;
    ipmb_addr = SLAVE_OWN_ADDRESS;
    currentRow=list_get_size();
    // 初始化 ID 号
    _size = sizeof(ipmc_id_table)/sizeof (ipmc_id_table[0]);
    memset(_ipmc_data, 0, sizeof (struct ipmc_data)*32);
    this->list_clear_addr();
    for(index=0; index<32; index++)
    {
        for(j=0; j<_size; j++ )
        {
            _ipmc_data[index].item[j].id = ipmc_id_table[j].id;
        }
    }
    //create_json();
}

void ipmc_protocolObj::pack_send_ipmc(struct ipmi_protocol *pack, const uint8_t slave_addr, const uint8_t NetFn, const uint8_t cmd, const uint8_t data)
{
    memset(pack, 0, sizeof(struct ipmi_protocol));
    pack->rsSA = slave_addr;              // 1:响应地址
    pack->NetFn = NetFn;		          // 2:网 络 功 能 码
    // 3;头部校验码
    pack->check_sum1 = calc_checksum_2byte(pack->rsSA, pack->NetFn);
    pack->rqSA = ipmb_addr;		          // 4:请求地址
    pack->rqSeq = static_cast<uint8_t>((cmd_rqSeq<<2) | 0x00);  // 5:请 求 序 列 号(rqSeq)及请求逻辑单元号 lun
    //pack->rqSeq = 0x11;
    pack->cmd = cmd;			          // 6:命令码
    pack->data[0] = data;		          // 7:命令数据
    pack->lenght = 1;			          // 命令数据长度
    cmd_rqSeq++;
    cmd_rqSeq &= 0x3F;
//    cmd_rqSeq = 0x11; // test
}
/**
| byte1 | byte2 | byte3 | byte4 | byte5 | byte6 | byte7 | byte8 |
| rsSA  | NetFn | sum1  | rqSA  | rqSeq | cmd   | data  | sum2  |
| ....  | buf[0]| buf[1]| buf[2]| buf[3]| buf[4]| buf[5]| buf[6]|
rsSA: IIC slave addr
*/
uint8_t ipmc_protocolObj::encode_send_ipmc(ipmi_protocol *pack, uint8_t buffer[], const uint8_t lenght)
{
    uint8_t i=0;
    memset(buffer, 0, lenght);
    buffer[0] = pack->NetFn;
    buffer[1] = pack->check_sum1;
    buffer[2] = pack->rqSA;
    buffer[3] = pack->rqSeq;
    buffer[4] = pack->cmd;
    for(i=0; i<pack->lenght; i++)
    {
        buffer[5+i] = pack->data[i];
    }
    // 计算从前面第 4 字节到倒数第 2 字节的校验码
    pack->check_sum2 = calc_checksum(&buffer[2], 6+i-1-2);
    buffer[5+i] = pack->check_sum2;
    return (6+i); // 返回 buffer 中数据长度
}

int ipmc_protocolObj::decode_send_ipmc(ipmi_protocol *pack, const uint8_t own_addr, const uint8_t buffer[], const uint8_t lenght)
{
    uint8_t check_sum = 0x00;
    memset(pack, 0, sizeof(struct ipmi_protocol));
    // 完全按照发送方的方式解出数据
    pack->rqSA = own_addr;                // 1:响应地址,即本机的 IIC 地址
    pack->NetFn = buffer[0];		      // 2:网 络 功 能 码
    pack->check_sum1 = buffer[1];         // 3;头部校验码
    pack->rsSA = buffer[2];		          // 4:请求地址
    pack->rqSeq = buffer[3];              // 5:请 求 序 列 号(rqSeq)及请求逻辑单元号 lun
    pack->cmd = buffer[4];			      // 6:命令码
    pack->data[0] = buffer[5];		      // 7:命令数据
    pack->lenght = 1;			          // 命令数据长度
    pack->check_sum2 = buffer[6];         // 8:字节 04h-07h 的校验码
    check_sum = calc_checksum_2byte(own_addr, pack->NetFn);
    if(check_sum != pack->check_sum1) goto bad;

    check_sum = calc_checksum(&buffer[2], lenght-1-2);
    if(check_sum != pack->check_sum2) goto bad;

    return 0;
bad:
    return -1;
}
/**
| byte1 | byte2 | byte3 | byte4 | byte5 | byte6 | byte7 | ...   | byte.n |
| rqSA  | NetFn | sum1  | rsSA  | rqSeq | cmd   | code  | data  | sum2   |
| ....  | buf[0]| buf[1]| buf[2]| buf[3]| buf[4]| buf[5]| ...   |buf[n-2]|
rqSA: IIC slave addr
*/
void ipmc_protocolObj::pack_send_cpu(struct ipmi_protocol *pack, const uint8_t slave_addr, const uint8_t NetFn, const uint8_t cmd, const uint8_t rqSeq, const uint8_t code, const uint8_t data1, const uint8_t data2, const uint8_t data3)
{
    memset(pack, 0, sizeof(struct ipmi_protocol));
    pack->rqSA = slave_addr;              // 1:响应地址, 主控板 CPU 的 IPMB 地址
    pack->NetFn = NetFn;		          // 2:网 络 功 能 码
    // 3;头部校验码
    pack->check_sum1 = calc_checksum_2byte(pack->rqSA, pack->NetFn);
    pack->rsSA = ipmb_addr;		          // 4:请求地址 , 电源板自己的 IPMB 地址
    // [0:1] lun 为 0 [2:7] rqSeq 为需要响应的命令的命令序号
    pack->rqSeq = rqSeq;                  // 5:请 求 序 列 号(rqSeq)及请求逻辑单元号 lun
    pack->cmd = cmd;			          // 6:命令码, 响应查询电流的命令码
    pack->code = code;			          // 7:完成码, 正常为 0x00，错误为 0xFF
    pack->data[0] = data1;		          // 8:命令数据 1
    pack->data[1] = data2;		          // 9:命令数据 2
    pack->data[2] = data3;		          // a:命令数据 3
    pack->lenght = 3;			          // 命令数据长度
}
/**
| byte1 | byte2 | byte3 | byte4 | byte5 | byte6 | byte7 | ...   | byte.n |
| rqSA  | NetFn | sum1  | rsSA  | rqSeq | cmd   | code  | data  | sum2   |
| ....  | buf[0]| buf[1]| buf[2]| buf[3]| buf[4]| buf[5]| ...   |buf[n-2]|
rqSA: IIC slave addr
*/
uint8_t ipmc_protocolObj::encode_send_cpu(ipmi_protocol *pack, uint8_t buffer[], const uint8_t lenght)
{
    uint8_t i=0;
    memset(buffer, 0, lenght);
    buffer[0] = pack->NetFn;
    buffer[1] = pack->check_sum1;
    buffer[2] = pack->rsSA;
    buffer[3] = pack->rqSeq;
    buffer[4] = pack->cmd;
    buffer[5] = pack->code;
    for(i=0; i<pack->lenght; i++)
    {
        buffer[6+i] = pack->data[i];
    }
    // 计算从前面第 4 字节到倒数第 2 字节的校验码
    pack->check_sum2 = calc_checksum(&buffer[2], 7+i-1-2);
    buffer[6+i] = pack->check_sum2;
    return (7+i); // 返回 buffer 中数据长度
}
/**
| IPMC →CPU
| byte1 | byte2 | byte3 | byte4 | byte5 | byte6 | byte7 | ...   | byte.n |
| rqSA  | NetFn | sum1  | rsSA  | rqSeq | cmd   | code  | data  | sum2   |
| ....  | buf[0]| buf[1]| buf[2]| buf[3]| buf[4]| buf[5]| ...   |buf[n-2]|
rqSA: IIC slave addr
Description: 解析 IPMC设备返回的数据
*/
int ipmc_protocolObj::decode_send_cpu(ipmi_protocol *pack, const uint8_t own_addr, const uint8_t buffer[], const uint8_t lenght)
{
    uint8_t check_sum = 0x00;
    memset(pack, 0, sizeof(struct ipmi_protocol));
    //qDebug("lenght:%d, 0x%02X", lenght, own_addr);
    // 完全按照发送方的方式解出数据
    pack->rqSA = own_addr;                // 1:响应地址, 主控板 CPU 的 IPMB 地址
    pack->NetFn = buffer[0];		      // 2:网 络 功 能 码
    // 3;头部校验码
    pack->check_sum1 = buffer[1];         // 3;头部校验码
    pack->rsSA = buffer[2];		          // 4:请求地址
    pack->rqSeq = buffer[3];              // 5:请 求 序 列 号(rqSeq)及请求逻辑单元号 lun
    pack->cmd = buffer[4];			      // 6:命令码
    pack->code = buffer[5];			      // 7:完成码, 正常为 0x00，错误为 0xFF
    pack->data[0] = buffer[6];		      // 8:命令数据 1
    pack->data[1] = buffer[7];		      // 9:命令数据 2
    pack->data[2] = buffer[8];		      // a:命令数据 3
    pack->lenght = 3;			          // 命令数据长度
    pack->check_sum2 = buffer[9];         // b:字节 04h-0ah 的校验码
    //qDebug("pack: 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7], buffer[8], buffer[9]);
    check_sum = calc_checksum_2byte(own_addr, pack->NetFn);
    //qDebug("check_sum1: 0x%02X, 0x%02X", check_sum, pack->check_sum1);
    if(check_sum != pack->check_sum1) goto bad;

    check_sum = calc_checksum(&buffer[2], lenght-1-2);
    //qDebug("check_sum2: 0x%02X, 0x%02X", check_sum, pack->check_sum2);
    if(check_sum != pack->check_sum2) goto bad;

    return 0;
bad:
    return -1;
}

int ipmc_protocolObj::decode_item(const ipmi_protocol *pack)
{
    uint8_t _solt_id = 0;
    uint8_t _item_id = 0;
#define CHECK_ID   1
//#undef  CHECK_ID
    _solt_id = search_solt_id(pack->rsSA); // 根据地址索引槽位号
    if((0x31<<2) != pack->NetFn)          // 校验网络码
    {
        goto bad;
    }
    // 根据槽位号存储数据
    // cmd
    switch(pack->cmd)
    {
        case 0xFF: // 电源板响应主机查询电流命令（IPMC →CPU）
            //printf("code:0x%02X, ID:0x%02X electricity：%d.%d A\r\n", pack_ipmc.code, pack_ipmc.data[2], pack_ipmc.data[0], pack_ipmc.data[1]);
            _item_id = search_item_id(pack->data[2]);
#ifdef CHECK_ID
            if((0x09>pack->data[2]) || (0x0E<pack->data[2]))
            {
                _ipmc_data[_solt_id].item[_item_id].code = 0x01; // 信息错误
                goto bad;
            }
#endif
            _ipmc_data[_solt_id].item[_item_id].code     = pack->code;
            //_ipmc_data[_solt_id].item[_item_id].id       = _item_id;
            _ipmc_data[_solt_id].item[_item_id].value    = pack->data[0]+pack->data[1]*0.01f;
            break;
        case 0xFE: // 电源板响应主机查询电压命令（IPMC →CPU）
            //printf("code:0x%02X, ID:0x%02X voltage：%d.%d V\r\n", pack_ipmc.code, pack_ipmc.data[2], pack_ipmc.data[0], pack_ipmc.data[1]);
            _item_id = search_item_id(pack->data[2]);
            //qDebug("code:0x%02X, ID:0x%02X [%d] voltage：%d.%d V\r\n", pack->code, pack->data[2], _item_id, pack->data[0], pack->data[1]);
#ifdef CHECK_ID
            // [0x02-0x08] && 0x11
            if((0x11!=pack->data[2]) && ((0x02>pack->data[2]) || (0x08<pack->data[2])))
            {
                _ipmc_data[_solt_id].item[_item_id].code = 0x01; // 信息错误
                goto bad;
            }
#endif
            _ipmc_data[_solt_id].item[_item_id].code     = pack->code;
            //_ipmc_data[_solt_id].item[_item_id].id       = _item_id;
            _ipmc_data[_solt_id].item[_item_id].value    = pack->data[0]+pack->data[1]*0.01f;
            break;
        case 0xFD: // 电源板响应主机查询温度命令（IPMC →CPU）
            // 电源板上温度 , 指示范围：-40  ～  125℃
            //printf("code:0x%02X, ID:0x%02X temperature：%d.%d C\r\n", pack_ipmc.code, pack_ipmc.data[2], pack_ipmc.data[0], pack_ipmc.data[1]);
            _item_id = search_item_id(pack->data[2]);
            //qDebug("code:0x%02X, ID:0x%02X [%d] temperature：%d.%d C\r\n", pack->code, pack->data[2], _item_id, pack->data[0], pack->data[1]);
#ifdef CHECK_ID
            // 0x01 && 0x10
            if((0x01 != pack->data[2]) && (0x10 != pack->data[2]))
            {
                _ipmc_data[_solt_id].item[_item_id].code = 0x01; // 信息错误
                goto bad;
            }
#endif
            _ipmc_data[_solt_id].item[_item_id].code     = pack->code;
            //_ipmc_data[_solt_id].item[_item_id].id       = _item_id;
            _ipmc_data[_solt_id].item[_item_id].value    = pack->data[0]+pack->data[1]*0.01f;
            break;
        case 0xFC: // 电源板响应主机查询自检状态命令（IPMC →CPU）
            //printf("code:0x%02X, status:0x%02X slot：%d type:0x%02X C\r\n", pack_ipmc.code, pack_ipmc.data[2], pack_ipmc.data[0], pack_ipmc.data[1]);
            /**
                 8  命令数据 1  08h  槽位号  电源板的槽位号，具体描述参照后续章节表 xxx 所示。
                 9  命令数据 2  09h  设备类型  详见设备类型定义所示。
                10  命令数据 3  0ah  设备状态  0x00：设备开机，0x01：设备关机
              */
            _ipmc_data[_solt_id].code     = pack->code;
            _ipmc_data[_solt_id].solt_id  = pack->data[0];
            _ipmc_data[_solt_id].dev_type = pack->data[1];
            _ipmc_data[_solt_id].status   = pack->data[2];
            break;
        default:
            break;
    }
    return 0;
bad:
    return -1;
}

int ipmc_protocolObj::list_insert_addr(const uint8_t _addr)
{
    uint8_t index=0;
    for(index=0; index<sizeof (list_ipmc_addr); index++)
    {
        if(_addr == list_ipmc_addr[index]) break;
        if(0 == list_ipmc_addr[index])
        {
            list_ipmc_addr[index] = _addr;
            list_ipmc_addr_max = index;
            return index;
        }
    }
    return -1;
}

#if 0
int ipmc_protocolObj::list_clear_addr()
{
    memset(list_ipmc_addr, 0, sizeof (list_ipmc_addr));
    currentRow = 0;
    list_ipmc_addr_max = 0;
    return  0;
}

int ipmc_protocolObj::create_json()
{
    uint16_t i=0;
    const char *path="ipmc_format.txt";
    cJSON* root =  cJSON_CreateObject();
    cJSON* objroot;// =  cJSON_CreateObject();
    char* json_str;

    cJSON_AddNumberToObject(root, "solt", 1);
    cJSON_AddNumberToObject(root, "type", 1);
    cJSON_AddNumberToObject(root, "status", 1);
    cJSON_AddNumberToObject(root, "code", 1);

    for(i=0; i<10; i++)
    {
        objroot =  cJSON_CreateObject();
        //cJSON_AddItemToObject(root, ("item"+QString::number(i)).toLocal8Bit().data(), objroot);
        cJSON_AddItemToObject(root, ("i"+QString::number(i)).toLocal8Bit().data(), objroot);
        cJSON_AddNumberToObject(objroot, "v", 1);
        cJSON_AddNumberToObject(objroot, "id", 0);
        cJSON_AddNumberToObject(objroot, "c", 1);
    }
    //json_str = cJSON_Print(root);
    json_str = cJSON_PrintUnformatted(root);
    QiTranslator::savecJSON(path, json_str);

//bad:
    cJSON_Delete(root);
    free(json_str);
    return 0;
}
#endif
int ipmc_protocolObj::list_clear_addr()
{
    memset(list_ipmc_addr, 0, sizeof (list_ipmc_addr));
    currentRow = 0;
    list_ipmc_addr_max = 0;
    return  0;
}

int ipmc_protocolObj::create_json()
{
    uint16_t i=0;
//    int numbers[3][3] =
//    {
//        {0, -1, 0},
//        {1, 0, 0},
//        {0 ,0, 1}
//    };
    int numbers[3] = {1000, -1234, 98765};
    const char *path="ipmc_format.txt";
    cJSON* root =  cJSON_CreateObject();
    cJSON* objroot;// =  cJSON_CreateObject();
    char* json_str;

    cJSON_AddNumberToObject(root, "solt", 1);
    cJSON_AddNumberToObject(root, "type", 1);
    cJSON_AddNumberToObject(root, "status", 1);
    cJSON_AddNumberToObject(root, "code", 1);

    objroot = cJSON_CreateArray();
    cJSON_AddItemToObject(root, ("i"+QString::number(i)).toLocal8Bit().data(), objroot);
//    for (i = 0; i < 3; i++)
//    {
//        cJSON_AddItemToArray(objroot, cJSON_CreateIntArray(numbers[i], 3));
//    }
//    cJSON_AddItemToObject(root, ("i"+QString::number(i)).toLocal8Bit().data(), objroot);
    for(i=0; i<16; i++)
    {
//        objroot = cJSON_CreateArray();
        cJSON_AddItemToArray(objroot, cJSON_CreateIntArray(numbers, 3));
        //objroot = cJSON_CreateIntArray(numbers, 3);
        //cJSON_AddItemToObject(root, ("item"+QString::number(i)).toLocal8Bit().data(), objroot);
        //cJSON_AddItemToObject(root, ("i"+QString::number(i)).toLocal8Bit().data(), objroot);
    }
    //cJSON_AddItemToObject(root, ("i"+QString::number(i)).toLocal8Bit().data(), objroot);
    json_str = cJSON_Print(root);
    //json_str = cJSON_PrintUnformatted(root);
    QiTranslator::savecJSON(path, json_str);

//bad:
    cJSON_Delete(root);
    free(json_str);
    return 0;
}

